<template>
<div class="file-list full-height relative-position">
  <div class="file-list-head row no-wrap bg-primary text-white">
    <span class="file-list-path ellipsis" ref="headPath">
      {{path}}
      <q-tooltip v-show="path.length > 0" :delay="1000" anchor="bottom left" self="bottom left">{{path}}</q-tooltip>
    </span>
    <q-space></q-space>
    <q-icon name="iconfont icontubiao-105" class="icon" @click="showRecycle()">
      <q-tooltip>回收站</q-tooltip>
    </q-icon>
    <q-icon v-if="allowBack" name="iconfont icontubiao-58" class="icon" @click="back()">
      <q-tooltip>返回上一级</q-tooltip>
    </q-icon>
    <q-icon :name="lookStatus==='list'?'iconfont icontubiao-104':'iconfont icontubiao-57'" class="icon" @click="changeLookStatus">
      <q-tooltip>切换显示模式</q-tooltip>
    </q-icon>
    <q-icon name="iconfont icontubiao-34" class="icon" @click="refresh">
      <q-tooltip>刷新</q-tooltip>
    </q-icon>
  </div>
  <div class="list-content drop-target relative-position" @dragenter="onDragEnter"
       @dragleave="onDragLeave" @dragover="onDragOver" @drop="onDrop"
       @mousedown="boxStart($event,'fileList')" ref="fileList"
  >
    <div class="full-height" v-if="lookStatus==='bigIcon'" @click.self="clearActFile">
      <q-scroll-area :thumb-style="thumbStyle" class="full-height">
        <div class="full-height list">
          <dl v-for="(file, fileIndex) in files" :key="fileIndex" :class="{'active': isActDay(file)}"
              @click.stop="selFile($event,file)" @dblclick.stop="dblclickE(file)"
              @contextmenu.stop="showMenu($event, 'menu'+fileIndex, file)" class="cloud-file-item"
              draggable="true" @dragstart="onDragStart($event, file)">
            <dt v-if="file.isFile"><q-icon :name="'img:statics/svg/'+file.type+'.svg'" style="font-size: 36px;"></q-icon></dt>
            <dt v-else><q-icon name="img:statics/svg/file-icon.svg" style="font-size: 36px;"></q-icon></dt>
            <dd>
              <div v-if="!file.edit" class="ellipsis-2-lines txt-ellipsis">{{file.label}}</div>
              <q-input class="name renameInput" :class="{'hidden':!file.edit}" v-model="rename" dense outlined
                       :ref="'renameInput1'+fileIndex" @keydown.native.enter="reNameBlur(file, $event)"
                       @blur="setNewNameFun(file, $event)" />
            </dd>
            <q-tooltip :delay="1000" anchor="bottom middle" self="center middle">{{file.label}}</q-tooltip>
            <q-menu :ref="'menu'+fileIndex" touch-position context-menu no-parent-event>
              <q-list dense style="min-width: 150px">
                <q-item clickable v-close-popup v-if="!file.isFile" @click="dblclickE(file)">
                  <q-item-section>打开下一级</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].cloud.rename.id,name:CommonConfig.statData[statPos].cloud.rename.name}"
                  clickable v-close-popup v-if="file.isFile" @click="renameFun(file)">
                  <q-item-section>重命名</q-item-section>
                </q-item>
                <q-item clickable v-close-popup v-if="file.isFile" @click="addCompareList(file)">
                  <q-item-section>加入对比列表</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].version.id,name:CommonConfig.statData[statPos].version.name}"
                  clickable v-close-popup v-if="file.isFile" @click="showVersionList(file)">
                  <q-item-section>版本履历</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].cloud.edit.id,name:CommonConfig.statData[statPos].cloud.edit.name}"
                  clickable v-close-popup v-if="file.isFile" @click="editFile(file)">
                  <q-item-section>编辑</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].cloud.del.id,name:CommonConfig.statData[statPos].cloud.del.name}"
                  clickable v-close-popup @click="deleteFun(file)">
                  <q-item-section>删除</q-item-section>
                </q-item>
              </q-list>
            </q-menu>
          </dl>
        </div>
      </q-scroll-area>
      <q-menu touch-position context-menu>
        <q-list dense style="min-width: 150px">
          <q-item clickable v-close-popup @click="newFolder">
            <q-item-section>新建文件夹</q-item-section>
          </q-item>
          <q-item clickable v-close-popup @click="newFile">
            <q-item-section>新建文件</q-item-section>
          </q-item>
        </q-list>
      </q-menu>
    </div>
    <div class="full-height" v-else @click.self="clearActFile">
      <q-table class="table-file" :pagination="pagination" no-data-label="暂无数据"
               :data="files" :columns="columns" row-key="id" hide-bottom
               binary-state-sort @request="onRequest">
        <template v-slot:body="props">
          <q-tr :props="props" @click.native.stop="selFile($event,props.row)" @dblclick.native.stop="dblclickE(props.row)"
                :class="{'active': isActDay(props.row)}"
                @contextmenu.native.stop="showMenu($event, 'menu'+props.row.index, props.row)"
                draggable="true" @dragstart="onDragStart($event, props.row)" class="cloud-file-item"
          >
            <q-td key="label" :props="props">
              <q-icon class="vertical-middle" v-if="props.row.isFile" :name="'img:statics/svg/'+props.row.type+'.svg'" style="font-size:18px;" />
              <q-icon class="vertical-middle" v-else name="img:statics/svg/file-icon.svg" style="font-size:18px;" />
              <span v-if="!props.row.edit" class="margin-l-10 name ellipsis">
                {{ props.row.label }}
                <q-tooltip :delay="1000">{{props.row.label}}</q-tooltip>
              </span>
              <q-input class="margin-l-10 name renameInput" :class="{'hidden':!props.row.edit}" v-model="rename" dense outlined
                       :ref="'renameInput2'+props.row.id" @keyup.enter="reNameBlur(props.row, $event)" @blur="setNewNameFun(props.row, $event)" />
            </q-td>
            <q-td key="size" :props="props">{{ props.row.isFile?sizeFormat(props.row.size):'—' }}</q-td>
            <q-td key="timestamp" :props="props">{{ dateFormat(props.row.timestamp) }}</q-td>
            <q-menu :ref="'menu'+props.row.index" touch-position context-menu no-parent-event>
              <q-list dense style="min-width: 150px">
                <q-item clickable v-close-popup v-if="!props.row.isFile" @click="dblclickE(props.row)">
                  <q-item-section>打开下一级</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].cloud.rename.id,name:CommonConfig.statData[statPos].cloud.rename.name}"
                  clickable v-close-popup v-if="props.row.isFile" @click="renameFun(props.row)">
                  <q-item-section>重命名</q-item-section>
                </q-item>
                <q-item clickable v-close-popup v-if="props.row.isFile" @click="addCompareList(props.row)">
                  <q-item-section>加入对比列表</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].version.id,name:CommonConfig.statData[statPos].version.name}"
                  clickable v-close-popup v-if="props.row.isFile" @click="showVersionList(props.row)">
                  <q-item-section>版本履历</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].cloud.edit.id,name:CommonConfig.statData[statPos].cloud.edit.name}"
                  clickable v-close-popup v-if="props.row.isFile" @click="editFile(props.row)">
                  <q-item-section>编辑</q-item-section>
                </q-item>
                <q-item
                  v-stat="{id:CommonConfig.statData[statPos].cloud.del.id,name:CommonConfig.statData[statPos].cloud.del.name}"
                  clickable v-close-popup @click="deleteFun(props.row)">
                  <q-item-section>删除</q-item-section>
                </q-item>
              </q-list>
            </q-menu>
          </q-tr>
        </template>
      </q-table>
      <q-menu touch-position context-menu>
        <q-list dense style="min-width: 150px">
          <q-item clickable v-close-popup @click="newFolder">
            <q-item-section>新建文件夹</q-item-section>
          </q-item>
          <q-item clickable v-close-popup @click="newFile">
            <q-item-section>新建文件</q-item-section>
          </q-item>
        </q-list>
      </q-menu>
    </div>
    <div class="box-select" ref="boxSelect"></div>
  </div>
<!--  版本履历-->
  <version-list ref="versionList"></version-list>
<!--  文件内容编辑插件-->
  <code-edit ref="codeEdit" :value="editFileContent" :name="editFileName" :decode="edtiFileDecode"
             :path="editFilePath" :state="codeState" @refreshList="refresh" @save="saveFile"></code-edit>
  <!--  文件发送确认弹框-->
  <send-sure-dialog ref="sendSure" :sender="sender" :acceptor="acceptor"
                    @removeItem="removeItem" @submit="sendFile"></send-sure-dialog>
  <!--  回收站弹框-->
  <recyclebin-dialog ref="recyclebin" :cur-path="nodeAct.path" @refresh="refresh"></recyclebin-dialog>
</div>
</template>

<script>
import { date } from 'quasar'
import { mapGetters } from 'vuex'
import CodeEdit from 'src/components/code-edit/index'
import SendSureDialog from './send-sure-dialog'
import RecyclebinDialog from './recyclebin-dialog'
import VersionList from './version-list'
import { getCloudList, setNewName, rmDir, rmFileToRecyclebin, newDir, newFile, readFile, editFile,
  getOSSAccount, cloudFileExist } from 'src/boot/program/cloud'
import { fileMachineLocal, cncToBox } from 'src/boot/program/machine'
import { getFilesForDict, getFileStats, getFileInfo } from 'src/assets/js/file-dir'
import { loadOss, saveOss } from 'src/assets/js/storage'
import { matchFileType, getOffsetLeft, getOffsetTop, getFiletype } from 'src/assets/js/util'
import boxCodeErr from 'src/assets/json/boxCodeErr'
import boxErr from 'src/assets/json/boxErr'
let OSS = require('ali-oss')
export default {
  name: 'file-list',
  props: {
    // 选中的树节点
    nodeAct: {
      type: Object
    },
    // 选中的文件
    seleFiles: {
      type: Array
    },
    state: { // 'local' / 'cloud' / 'machine
      type: String,
      default: 'local'
    },
    // 拖动的item
    dragItem: {
      type: Array
    },
    // 邻居文件列表选中的文件
    siblingNode: {
      type: Object
    },
    // 设备传输文件mqtt工具
    client: {},
    // 埋点所在位置
    statPos: {
      type: String
    }
  },
  computed: {
    // 是否显示返回上一级按钮
    allowBack () {
      return !(this.nodeAct.desk || this.nodeAct.disk || this.nodeAct.root)
    },
    path () {
      let pathArr = this.nodeAct.path.split('/')
      pathArr.shift()
      return '所有文件/' + pathArr.join('/')
    },
    ...mapGetters(['userInfo'])
  },
  data () {
    return {
      thumbStyle: this.CommonConfig.thumbStyle, // 滚动条样式
      actFile: [], // 选中的文件
      clickTime: null, // 区分单击与双击
      lookStatus: 'bigIcon', // 查看状态, list or bigIcon
      columns: [ // 列表的头部
        { name: 'label', align: 'left', label: '文件名', field: 'label', style: 'width: 60%' },
        { name: 'size', align: 'left', label: '大小', field: 'size' },
        { name: 'timestamp', label: '修改时间', field: 'timestamp', sortable: true }
      ],
      pagination: {
        sortBy: '',
        descending: false,
        page: 1,
        rowsPerPage: 0,
        rowsNumber: 10
      },
      rename: '', // 重命名
      files: [],
      emptyMenu: false, // 控制空白处右键显示的菜单
      editFileContent: '', // 要编辑文件的内容
      editFileName: '', // 要编辑文件的名字
      edtiFileDecode: '', // 要编辑文件的编码
      editFilePath: '', // 要编辑文件的路径
      codeState: 'edit', // 添加编辑状态，state or add
      sender: { // 发送方
        source: 'local',
        data: []
      },
      acceptor: { // 接收方
        source: 'cloud',
        data: []
      },
      clientCloud: null, // 文件传输用
      // 框选数据
      parentW: 0, // 外框的宽
      parentH: 0, // 外框的高
      parentX: 0, // 外框的横坐标
      parentY: 0, // 外框的中坐标
      programArr: [], // 传输列表
      transfering: false // 是否在传输中
    }
  },
  watch: {
    seleFiles (newVal) {
      this.actFile = []
      this.files = newVal.map((item, index) => {
        return {
          index,
          ...item,
          edit: false
        }
      })
    }
  },
  created () {
    this.files = this.seleFiles.map(item => {
      return {
        ...item,
        edit: false
      }
    })
  },
  mounted () {
  },
  methods: {
    // 切换显示模式
    changeLookStatus () {
      this.lookStatus = this.lookStatus === 'list' ? 'bigIcon' : 'list'
    },
    // 重置数据
    initInfo (info, isFile) {
      return info.map(item => {
        ++this.id
        return {
          ...item,
          id: this.id,
          _name: item.label,
          isFile: isFile,
          type: isFile ? getFiletype(item.label) : 'other',
          lazy: true,
          source: 'cloud', // 文件来源，云端
          children: []
        }
      })
    },
    // 选中文件
    selFile (e, item) {
      clearTimeout(this.clickTime)
      // const self = this
      this.clickTime = setTimeout(() => {
        if (e.ctrlKey) {
          // 按住ctrl键
          const index = this.actFile.findIndex(file => {
            return file.id === item.id
          })
          if (index > -1) {
            this.actFile = this.actFile.filter(file => {
              return file.id !== item.id
            })
          } else {
            this.actFile.push(item)
          }
        } else if (e.shiftKey) {
          // 按住shift键
          if (this.actFile.length === 0) {
            this.actFile.push(item)
          } else {
            const maxIndex = this.getMaxIndex()
            const index = this.seleFiles.findIndex(file => {
              return file.id === item.id
            })
            let actFile = this.seleFiles.filter((file, fileIndex) => {
              const condition = (index > maxIndex && fileIndex <= index && fileIndex >= maxIndex) ||
                (index < maxIndex && fileIndex >= index && fileIndex <= maxIndex) ||
                (index === maxIndex && fileIndex === index)
              return condition
            })
            this.actFile = actFile
          }
        } else {
          // 单选
          const index = this.actFile.findIndex(file => {
            return file.id === item.id
          })
          this.actFile = index > -1 ? [] : [item]
        }
        this.$emit('refreshSelFile', 'cloud', this.actFile)
      }, 250)
    },
    // 获取存储在选中的file里面的最大最小角标
    getMaxIndex () {
      const indexArr = []
      this.actFile.forEach(item => {
        const index = this.seleFiles.findIndex(file => {
          return file.id === item.id
        })
        if (index > -1) {
          indexArr.push(index)
        }
      })
      indexArr.sort((a, b) => a > b ? 1 : -1)
      return indexArr[indexArr.length - 1]
    },
    // 是否是选中状态
    isActDay (file) {
      const index = this.actFile.findIndex(item => {
        return item.id === file.id
      })
      return index > -1
    },
    // 清空选中文件列表
    clearActFile () {
      this.actFile = []
      this.$emit('refreshSelFile', 'cloud', this.actFile)
    },
    clearActFile1 () {
      this.actFile = []
    },
    // 双击进入子级文件夹
    dblclickE (file) {
      clearTimeout(this.clickTime)
      if (!file.isFile) {
        this.actFile = []
        this.getFile(file)
      }
    },
    // 显示回收站
    showRecycle () {
      this.$refs.recyclebin.showDialog()
    },
    // 返回上一级
    back () {
      this.$emit('back')
    },
    // 时间格式化
    dateFormat (timestamp) {
      return date.formatDate(timestamp, 'YYYY-MM-DD HH:mm:ss')
    },
    // 文件大小格式化
    sizeFormat (size) {
      if (size === 0) {
        return '0B'
      } else if (size / 1024 < 1) {
        return size + 'B'
      } else if (size / 1024 / 1024 < 1) {
        return (size / 1024).toFixed(2) + 'K'
      } else if (size / 1024 / 1024 / 1024 < 1) {
        return (size / 1024 / 1024).toFixed(2) + 'M'
      } else {
        return (size / 1024 / 1024 / 1024).toFixed(2) + 'G'
      }
    },
    // 刷新
    refresh () {
      this.getFile(this.nodeAct)
    },
    // 获取文件列表
    getFile (node) {
      getCloudList(node.path).then(res => {
        let dirs = this.initInfo(res.data.dirs, false)
        let files = this.initInfo(res.data.files, true)
        let nodes = [].concat(dirs, files)
        this.$emit('infoDir', node, nodes, dirs)
      })
    },
    // 重命名显示输入框
    renameFun (item) {
      this.rename = item.label
      this.resetEdit(item)
      // 设置选中区域
      this.$nextTick(() => {
        const input = this.$refs['renameInput' + (this.lookStatus === 'list' ? 2 : 1) + item.id]
        const dominput = input.constructor === Array ? input[0].$refs.input : input.$refs.input
        const endPos = this.getTxtPos(item.label)
        if (dominput.setSelectionRange) {
          dominput.focus()
          dominput.setSelectionRange(0, endPos)
        } else if (dominput.createTextRange) {
          var range = dominput.createTextRange
          range.collapse(true)
          range.moveStart('character', 0)
          range.moveEnd('character', endPos)
          range.select()
        }
      })
    },
    // 获取选中区域的终止位置
    getTxtPos (label) {
      let txtArr = label.split('.')
      if (txtArr.length === 1) {
        return label.length
      }
      const lastLength = txtArr[txtArr.length - 1].length
      return label.length - lastLength - 1
    },
    // 设置编辑状态
    resetEdit (actItem) {
      this.files = this.files.map(item => {
        return {
          ...item,
          edit: actItem.id === item.id
        }
      })
    },
    // 退出重命名状态
    blur () {
      this.files = this.files.map(item => {
        return {
          ...item,
          edit: false
        }
      })
    },
    // 重命名文件夹、文件
    setNewNameFun (item, event) {
      // 如果名字没有变化，就这样了
      if (item.label === this.rename) {
        // event.target.blur()
        item.edit = false
        return
      }

      let path = item.isFile ? item.path : item.path.slice(0, item.path.length - 1)
      const params = {
        newKey: this.rename,
        oldKey: path
      }
      setNewName(params).then(res => {
        this.refresh()
      }).catch(() => {
        this.rename = item.label
      })
    },
    reNameBlur (item, event) {
      event.target.blur()
    },
    // 删除文件和文件夹
    deleteFun (item) {
      this.$q.dialog({
        title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 确定要删除${item.label}吗？</p>`,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        },
        cancel: {
          unelevated: true,
          outline: true,
          label: '取消'
        }
      }).onOk(data => {
        // if (this.actFile.length > 1) {
        //   this.batchDeleteFun()
        //   return false
        // }
        if (item.isFile) {
          let path = item.path
          rmFileToRecyclebin(path, item.size).then(res => {
            this.refresh()
          })
        } else {
          let path = item.path
          rmDir(path).then(res => {
            this.refresh()
          })
        }
      })
    },
    // 批量删除
    // batchDeleteFun () {
    //   let params = this.actFile.map(item => {
    //     return {
    //       path: item.path,
    //       isFile: item.isFile
    //     }
    //   })
    //   batchFileDir({ list: params }).then(res => {
    //     if (res.data.errCount > 0) {
    //       let message = ''
    //       res.data.errItems.forEach(item => {
    //         message += item.label
    //       })
    //       message += '删除失败'
    //       this.errMessage(message)
    //     }
    //     this.refresh()
    //     this.actFile = []
    //   })
    // },
    // 新建文件夹
    newFolder () {
      this.$q.dialog({
        class: 'prompt-dialog',
        title: '文件夹名称',
        prompt: {
          model: '',
          isValid: val => val.length > 0 && val.length < 20,
          type: 'text'
        },
        ok: {
          unelevated: true,
          label: '确认'
        },
        cancel: {
          unelevated: true,
          outline: true,
          label: '取消'
        },
        persistent: true
      }).onOk(data => {
        if (data.length === 0) {
          this.$q.dialog({
            title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
            message: '名称不能为空',
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          return false
        }
        if (data.length > 20) {
          this.$q.dialog({
            title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
            message: '名称长度必须小于20',
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          return false
        }
        let findIndex = this.files.findIndex(item => !item.isFile && item.label === data)
        if (findIndex > -1) {
          this.$q.dialog({
            title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
            message: `文件夹${data}已存在`,
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          return false
        }
        let path = this.nodeAct.path === '' ? this.userInfo.tenant_id + '/' : this.nodeAct.path
        newDir(path + data + '/').then(res => {
          this.getFile(this.nodeAct)
        })
      })
    },
    // 新建文件
    newFile () {
      this.$q.dialog({
        class: 'prompt-dialog',
        title: '文件名称',
        prompt: {
          model: '',
          type: 'text'
        },
        ok: {
          unelevated: true,
          label: '确认'
        },
        cancel: {
          unelevated: true,
          outline: true,
          label: '取消'
        },
        persistent: true
      }).onOk(data => {
        if (data.length === 0) {
          this.$q.dialog({
            title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
            message: '名称不能为空',
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          return false
        }
        if (data.length > 20) {
          this.$q.dialog({
            title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
            message: '名称长度必须小于20',
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          return false
        }
        let findIndex = this.files.findIndex(item => item.isFile && item.label === data)
        if (findIndex > -1) {
          this.$q.dialog({
            title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
            message: `文件${data}已存在`,
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          return false
        }
        this.editFilePath = this.nodeAct.path + data
        this.editFileName = data
        this.editFileContent = ''
        this.edtiFileDecode = ''
        this.codeState = 'add'
        this.$refs.codeEdit.showDialog()
      })
    },
    // 失败提示
    errMessage (message) {
      this.$q.dialog({
        title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-52" ></i> 提示</p>`,
        message: message,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        }
      })
    },
    // 右键显示选中的文件或文件夹的菜单
    showMenu (event, ref, item) {
      const ele = this.$refs[ref]
      if (ele) {
        ele.constructor === Array ? this.$refs[ref][0].show(event) : this.$refs[ref].show(event)
      }
      // 单选
      const index = this.actFile.findIndex(file => {
        return file.id === item.id
      })
      this.actFile = index > -1 ? [] : [item]
      this.$emit('refreshSelFile', 'cloud', this.actFile)
    },
    // 编辑读取文件
    editFile (item) {
      if (matchFileType(item.label)) {
        this.errMessage('无法编辑图片文件、word文件、视频文件、音频文件、快捷方式、压缩文件！')
        return
      }
      if (!this.testFileSize(item)) return
      this.editFileName = item.label
      readFile(item.path).then(res => {
        this.editFileContent = res.data
        this.editFilePath = item.path
        this.codeState = 'edit'
        this.$refs.codeEdit.showDialog()
      })
    },
    // 验证文件大小是否超过5M
    testFileSize (file) {
      if (file.size > 5 * 1024 * 1024) {
        this.errMessage('文件超过5M暂不支持查看！')
        return false
      }
      return true
    },
    // 保存文件
    saveFile (fileName, code) {
      let frontPath = this.nodeAct.path === '' ? this.userInfo.tenant_id + '/' : this.nodeAct.path
      let nameArr = fileName.split('/')
      if (this.codeState === 'add') {
        const params = {
          dir: frontPath,
          fileName: nameArr[nameArr.length - 1],
          content: code
        }
        newFile(params).then(res => {
          let successMessage = `<p class="dialog-notice-title"><i class="iconfont icontubiao-53"></i>
${this.codeState === 'edit' ? '修改' : '添加'}文件${this.editFileName}成功</p>`
          this.$q.dialog({
            title: successMessage,
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          this.refresh()
          this.$refs.codeEdit.hideDialog()
        })
      } else if (this.codeState === 'edit') {
        const params = {
          key: fileName,
          content: code
        }
        editFile(params).then(res => {
          let successMessage = `<p class="dialog-notice-title"><i class="iconfont icontubiao-53"></i> ${this.codeState === 'edit' ? '修改' : '添加'}文件${this.editFileName}成功</p>`
          this.$q.dialog({
            title: successMessage,
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          this.refresh()
          this.$refs.codeEdit.hideDialog()
        })
      }
    },
    // 加入对比列表
    addCompareList (file) {
      const saveFile = {
        ...file, source: 'cloud'
      }
      this.$emit('showCompareList', saveFile)
      this.actFile = []
    },
    // 显示版本履历
    showVersionList (file) {
      this.versionFile = file
      this.$refs.versionList.showDialog(file)
    },
    // 拖动功能
    // store the id of the draggable element
    onDragStart (e, dragItem) {
      e.dataTransfer.setData('text', e.target.id)
      e.dataTransfer.dropEffect = 'move'
      const index = this.actFile.findIndex(file => {
        return file.id === dragItem.id
      })
      if (index === -1) {
        // this.actFile.push(dragItem)
        this.actFile = [dragItem]
      }
      this.$emit('setDragItem', this.actFile)
    },
    onDragEnter (e) {
      // don't drop on other draggables
      if (e.target.draggable !== true) {
        e.target.classList.add('drag-enter')
      }
    },
    onDragLeave (e) {
      e.target.classList.remove('drag-enter')
    },
    onDragOver (e) {
      e.preventDefault()
    },
    onDrop (e) {
      e.preventDefault()

      // don't drop on other draggables
      if (e.target.draggable === true || this.dragItem[0].source === 'cloud') {
        return
      }
      let sendData
      if (this.dragItem[0].source === 'machine') {
        sendData = this.dragItem.filter(item => item.isFile)
      } else {
        sendData = this.dragItem
      }
      this.sender = {
        source: this.dragItem[0].source,
        data: sendData
      }
      this.acceptor = {
        source: 'cloud',
        data: [this.nodeAct]
      }
      this.$refs.sendSure.showDialog()
    },
    // 验证要发送的文件是否符合规则
    testSendFile (files) {
      for (let i = 0; i < files.length; i++) {
        if (files[i].size > 50 * 1024 * 1024) {
          this.errMessage(`文件${files[i].label}大小超过50M，请重新选择要上传文件`)
          return false
        }
      }
      return true
    },
    // 验证要发送的本地文件是否符合规则
    testSendLocalFile (files) {
      for (let i = 0; i < files.length; i++) {
        let info = getFileInfo(files[i][0])
        if (info.size > 50 * 1024 * 1024) {
          this.errMessage(`文件${files[i][1]}大小超过50M，请重新选择要上传文件`)
          return false
        }
      }
      return true
    },
    // 发送确认框，移除某一项
    removeItem (postion, item) {
      if (postion === 'send') {
        this.sender.data = this.sender.data.filter(i => {
          return item.label !== i.label && item.path !== i.path
        })
      }
      if (postion === 'accept') {
        this.acceptor.data = this.acceptor.data.filter(i => {
          return item.label !== i.label && item.path !== i.path
        })
      }
      if (this.sender.data.length === 0 || this.acceptor.data.length === 0) {
        this.$refs.sendSure.hideDialog()
      }
    },

    // 判断接收的是本地文件还是机器文件
    sendFile () {
      this.$refs.sendSure.hideDialog()
      if (this.sender.source === 'local') {
        this.getOss()
      } else if (this.sender.source === 'machine') {
        this.getMachineFile()
      }
    },

    // 本地到云端
    // 将本地文件发送给云端
    sendCloud (oss) {
      this.clientCloud = new OSS({
        region: oss.region,
        accessKeyId: oss.accessKeyId,
        accessKeySecret: oss.accessKeySecret,
        stsToken: oss.securityToken,
        bucket: oss.bucket
      })
      const files = getFilesForDict(this.sender.data)
      if (files.length > 50) { // 超过50个不能上传
        this.errMessage('不能超过50个文件')
        return false
      }
      // 验证文件大小不能超过50M
      if (!this.testSendLocalFile(files)) {
        return false
      }
      let dirs = []
      let siblingNodePath = this.siblingNode.path.replace(/\\/g, '/')
      // 遍历每个文件，获取blob对象，发送文件
      this.acceptor.data.forEach(accept => {
        files.forEach(send => {
          let path = send[0].replace(/\\/g, '/').replace(siblingNodePath, '').replace(send[1], '')
          if (path.length > 0) {
            dirs.push(path)
          }
          // 判断文件是否存在
          let savePath = (accept.path === '' ? this.userInfo.tenant_id + '/' : accept.path) + send[1]
          cloudFileExist(savePath).then(res => {
            if (res.data) {
              this.$q.dialog({
                title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
                message: '文件' + send[1] + '已存在，是否覆盖文件',
                html: true,
                ok: {
                  unelevated: true,
                  label: '确认'
                },
                cancel: {
                  unelevated: true,
                  outline: true,
                  label: '取消'
                },
                persistent: true
              }).onOk(data => {
                // 读取文件信息，生成blob
                getFileStats(send, accept.path, this.put)
              })
            } else {
              // 读取文件信息，生成blob
              getFileStats(send, accept.path, this.put)
            }
          })
        })
      })
      let dirSet = new Set(dirs)
      let newDirs = Array.from(dirSet)
      this.newDirs(newDirs)
    },
    // 发送本地文件的方法
    async put (sendFile, send, acceptPath) {
      let self = this
      let path = acceptPath.length === 0 ? this.userInfo.tenant_id + '/' : acceptPath
      let newPath = this.getShowCloudPath(path)
      let path1 = send[0].replace(/\\/g, '/').replace(this.siblingNode.path, '')
      let path1s = path1.split('/')
      path1s.pop()
      path1 = path1s.length > 0 ? path1s.join('/') + '/' : ''
      // 获取当前发送信息
      let file = this.sender.data.find(item => {
        return item.label === send[1]
      })
      try {
        let checkpoint
        let startTime = new Date()
        const result = await this.clientCloud.multipartUpload(path + path1 + send[1], sendFile, {
          checkpoint,
          async progress (percentage, cpt) {
            checkpoint = cpt
            if (cpt) {
              let progress = {
                name: send[1], // 文件名字
                progress: percentage, // 传输进度
                state: 'upload', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
                partSize: cpt.partSize.toFixed(2), // 每次上传的大小
                fileSize: file.size, // 文件总大小
                acceptPath: newPath + path1 + send[1], // 接收方地址
                startTime, // 开始时间
                sender: self.sender.source, // 发送方
                acceptor: self.acceptor.source, // 接收方
                endTime: self.dateToString(new Date()),
                useTime: self.getUseTime(startTime, new Date())
              }
              self.$emit('addProgressFiles', progress)
            }
          },
          partSize: 100 * 1024,
          timeout: 120000 // 超时时间
        })
        if (result.res.status === 200) {
          // let file = this.sender.data.find(item => {
          //   return item.name === send[1]
          // })
          // console.log(file)
          let progress = {
            name: send[1], // 文件名字
            progress: 1, // 传输进度
            state: 'success', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
            partSize: 100 * 1024, // 每次上传的大小
            fileSize: file.size, // 文件总大小
            acceptPath: newPath + path1 + send[1], // 接收方地址
            startTime, // 开始时间
            sender: self.sender.source, // 发送方
            acceptor: self.acceptor.source, // 接收方
            endTime: self.dateToString(new Date()),
            useTime: self.getUseTime(startTime, new Date())
          }
          self.$emit('addProgressFiles', progress)
        } else {
          let progress = {
            name: send[1], // 文件名字
            progress: 1, // 传输进度
            state: 'fail', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
            partSize: 100 * 1024, // 每次上传的大小
            fileSize: file.size, // 文件总大小
            acceptPath: newPath + path1 + send[1], // 接收方地址
            startTime, // 开始时间
            sender: self.sender.source, // 发送方
            acceptor: self.acceptor.source, // 接收方
            reason: '',
            endTime: self.dateToString(new Date()),
            useTime: self.getUseTime(startTime, new Date())
          }
          self.$emit('addProgressFiles', progress)
        }
        this.refresh()
      } catch (e) {
        console.error(e)
        let progress = {
          name: send[1], // 文件名字
          progress: 1, // 传输进度
          state: 'fail', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
          partSize: 100 * 1024, // 每次上传的大小
          fileSize: file.size, // 文件总大小
          acceptPath: newPath + path1 + send[1], // 接收方地址
          startTime: new Date(), // 开始时间
          sender: self.sender.source, // 发送方
          acceptor: self.acceptor.source, // 接收方
          reason: '',
          endTime: self.dateToString(new Date()),
          useTime: '00:00:00'
        }
        self.$emit('addProgressFiles', progress)
      }
    },
    // 上传本地时创建新文件夹
    newDirs (dirs) {
      let nodeActPath = this.nodeAct.path.length > 0 ? this.nodeAct.path : this.userInfo.tenant_id + '/'
      dirs.forEach((dir, dirIndex) => {
        let dirArr = dir.slice(0, dir.length - 1).replace(/\\/g, '/').split('/')
        dirArr.forEach((item, index) => {
          let subDirName = dirArr.slice(0, index + 1)
          let testName = subDirName.join('/') + '/'
          newDir(nodeActPath + testName).then(res => {
            this.getFile(this.nodeAct)
          })
        })
      })
    },
    // 获取oss账号
    getOss () {
      let oss = loadOss()
      if (!oss && !oss.expiration) {
        this.refreshOSSAccout()
      } else {
        let overTime = new Date(oss.expiration)
        let now = new Date()
        if (now.getTime() < overTime.getTime() - 60) {
          this.sendCloud(oss)
        } else {
          this.refreshOSSAccout()
        }
      }
    },
    // 更新oss账号
    refreshOSSAccout () {
      getOSSAccount().then(res => {
        let oss = res.data
        saveOss(oss)
        this.sendCloud(oss)
      })
    },

    // 机器到云端
    // 机器文件传到云端
    getMachineFile () {
      if (this.sender.data.length > 50) {
        this.errMessage('不能超过50个文件')
        return false
      }
      // 验证文件大小不能超过50M
      if (!this.testSendFile(this.sender.data)) {
        return false
      }
      // 遍历每个文件，获取blob对象，发送文件
      this.acceptor.data.forEach(accept => {
        this.sender.data.forEach(send => {
          // 判断文件是否存在
          let savePath = (accept.path === '' ? this.userInfo.tenant_id + '/' : accept.path) + send.label
          cloudFileExist(savePath).then(res => {
            if (res.data) {
              this.$q.dialog({
                title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
                message: '文件' + send.label + '已存在，是否覆盖文件',
                html: true,
                ok: {
                  unelevated: true,
                  label: '确认'
                },
                cancel: {
                  unelevated: true,
                  outline: true,
                  label: '取消'
                },
                persistent: true
              }).onOk(data => {
                // 开始发送文件
                // if (send.position === 'cnc') {
                //   this.putMachineInside(send, accept)
                // } else {
                //   this.putMachine(send, accept)
                // }
                console.log(send.path, 1137)
                this.addProgramArrMachine(send, accept)
                this.startProgramMachine()
              })
            } else {
              // 开始发送文件
              // if (send.position === 'cnc') {
              //   this.putMachineInside(send, accept)
              // } else {
              //   this.putMachine(send, accept)
              // }
              this.addProgramArrMachine(send, accept)
              this.startProgramMachine()
            }
          })
        })
      })
      this.startProgramMachine()
    },
    // 添加到传输列表
    addProgramArrMachine (send, accept) {
      console.log(send.path, 1156)
      this.programArr.push({
        send,
        acceptPath: accept.path,
        accept
      })
      let startTime = new Date()
      // let savePath = (accept.path === '' ? this.userInfo.tenant_id + '/' : accept.path) + send.label
      let savePath = (accept.path === '' ? '所有文件' + '/' : accept.path.replace(this.userInfo.tenant_id, '所有文件')) + send.label
      savePath = this.getShowCloudPath(savePath)
      let progress = {
        name: send.label, // 文件名字
        progress: 0, // 传输进度
        state: 'upload', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
        partSize: 16, // 每次上传的大小
        fileSize: 0, // 文件总大小
        acceptPath: savePath, // 接收方地址
        startTime, // 开始时间
        sender: this.sender.source, // 发送方
        acceptor: this.acceptor.source, // 接收方
        endTime: this.dateToString(new Date()),
        useTime: this.getUseTime(startTime, new Date())
      }
      this.$emit('addProgressFiles', progress)
    },
    // 传输一个文件
    startProgramMachine () {
      // 如果此时已在传输中，这次请求就打回
      if (this.transfering) {
        return
      }
      if (this.programArr.length > 0) {
        let program = this.programArr.shift()
        this.transfering = true
        if (program.send.position === 'cnc') {
          this.putMachineInside(program.send, program.accept)
        } else {
          this.putMachine(program.send, program.accept)
        }
      }
    },
    // 开始发送内部存储文件到外部存储文件
    putMachineInside (send, accept) {
      let self = this
      let requestId1 = 'webClient' + this.userInfo.user_id.toString() + Date.parse(new Date()).toString()

      let params1 = {
        boxId: send.boxId,
        cncPath: send.path,
        requestId: requestId1
      }
      this.$emit('onSubscribe', send.boxId)
      cncToBox(params1)
      let savePath = (accept.path === '' ? this.userInfo.tenant_id + '/' : accept.path) + send[1]
      // let savePath = (accept.path === '' ? '所有文件' + '/' : accept.path.replace(this.userInfo.tenant_id, '所有文件')) + send[1]
      savePath = this.getShowCloudPath(savePath)
      this.client.onMessageArrived = (message) => {
        let data = JSON.parse(message.payloadString)
        try {
          // 这里是防止对其他消息进行处理
          if (requestId1 === data.request_id &&
            message.destinationName === `${this.CommonConfig.mqttConfig.MQTT_TOPIC.machineFileInfo.subscribeTopic}${send.boxId}`) {
            if (data.hasOwnProperty('error') && data.error === 0) {
              // send.path = data.file_path
              let downloadPath = data.file_path
              this.putMachine(send, accept, downloadPath)
            } else {
              let progress = {
                name: send.label, // 文件名字
                progress: 1, // 传输进度
                state: 'fail', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
                partSize: 16, // 每次上传的大小
                fileSize: send.size, // 文件总大小
                acceptPath: savePath, // 接收方地址
                startTime: new Date(), // 开始时间
                sender: self.sender.source, // 发送方
                acceptor: self.acceptor.source, // 接收方
                reason: boxErr[data.code], // 传输失败原因
                endTime: self.dateToString(new Date()),
                useTime: '00:00:00'
              }
              self.$emit('addProgressFiles', progress)
            }
          }
        } catch (e) {
          console.error(e)
          this.errMessage('传输文件失败')
          let progress = {
            name: send.label, // 文件名字
            progress: 1, // 传输进度
            state: 'fail', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
            partSize: 16, // 每次上传的大小
            fileSize: send.size, // 文件总大小
            acceptPath: savePath, // 接收方地址
            startTime: new Date(), // 开始时间
            sender: self.sender.source, // 发送方
            acceptor: self.acceptor.source, // 接收方
            reason: boxErr[data.code], // 传输失败原因
            endTime: self.dateToString(new Date()),
            useTime: '00:00:00'
          }
          self.$emit('addProgressFiles', progress)
        }
      }
    },
    // 开始发送外部存储文件
    putMachine (send, accept, downloadPath = '') {
      let self = this

      let params = {
        boxId: send.boxId,
        fileName: send.label,
        filePath: downloadPath.length > 0 ? downloadPath : send.path,
        fromBox: send.position === 'box' ? 1 : 0,
        cloudPath: (accept.path === '' ? this.userInfo.tenant_id + '/' : accept.path)
      }
      let requestId, url
      fileMachineLocal(params).then(res => {
        requestId = res.data.requestId
        url = res.data.url
        console.log(url)
        this.$emit('onSubscribe1', res.data.requestId)
        this.$emit('onSubscribe2', res.data.requestId)
        // let params1 = {
        //   boxId: send.boxId,
        //   cncPath: url,
        //   requestId
        // }
        // cncToBox(params1)
      })
      // 上一个进度
      let lastProgress = null, progress
      // 上传开始时间
      let startTime = new Date()
      let savePath = (accept.path === '' ? this.userInfo.tenant_id + '/' : accept.path) + send.label
      savePath = this.getShowCloudPath(savePath)
      this.client.onMessageArrived = (message) => {
        let data = JSON.parse(message.payloadString)
        // 这里是放置对其他消息进行处理
        try {
          if (requestId === data.request_id) {
            if (data.hasOwnProperty('source') && data.source === 'send_result') {
              // 对外部存储传输失败进行处理
              if (data.code !== 200) {
                progress = {
                  name: send.label, // 文件名字
                  progress: 1, // 传输进度
                  state: 'fail', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
                  partSize: 16, // 每次上传的大小
                  fileSize: send.size, // 文件总大小
                  acceptPath: savePath, // 接收方地址
                  startTime: new Date(), // 开始时间
                  sender: self.sender.source, // 发送方
                  acceptor: self.acceptor.source, // 接收方
                  reason: boxCodeErr[data.code], // 传输失败原因
                  endTime: self.dateToString(new Date()),
                  useTime: self.getUseTime(startTime, new Date())
                }
                self.$emit('addProgressFiles', progress)
                // 开始上传下一个
                this.transfering = false
                this.startProgramMachine()
              } else {
                progress = {
                  name: send.label, // 文件名字
                  progress: 1, // 传输进度
                  state: 'success', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
                  partSize: 16, // 每次上传的大小
                  fileSize: send.size, // 文件总大小
                  acceptPath: savePath, // 接收方地址
                  startTime: new Date(), // 开始时间
                  sender: self.sender.source, // 发送方
                  acceptor: self.acceptor.source, // 接收方
                  endTime: self.dateToString(new Date()),
                  useTime: self.getUseTime(startTime, new Date())
                }
                self.$emit('addProgressFiles', progress)
                // 开始上传下一个
                this.transfering = false
                this.startProgramMachine()
                this.refresh()
              }
            } else if (data.rate && (lastProgress === null || lastProgress.progress < data.rate)) {
              // 这里是防止进度数据混乱
              let progress = {
                name: send.label, // 文件名字
                progress: data.rate, // 传输进度
                state: 'download', // 上传状态 upload:正在上传，download:正在下载，success：传输成功，fail：传输失败
                partSize: 16, // 每次上传的大小
                fileSize: send.size, // 文件总大小
                acceptPath: savePath, // 接收方地址
                startTime, // 开始时间
                sender: self.sender.source, // 发送方
                acceptor: self.acceptor.source, // 接收方
                endTime: self.dateToString(new Date()),
                useTime: self.getUseTime(startTime, new Date())
              }
              lastProgress = progress
              self.$emit('addProgressFiles', progress)
            }
          }
        } catch (e) {
          console.error(e)
          this.errMessage('传输文件失败')
        }
      }
    },
    // 根据开始时间和结束时间，获取累计用时时间，返回hh:mm:ss
    getUseTime (startTime, endTime) {
      let useTime = (endTime.getTime() - startTime.getTime()) / 1000
      let seconds = parseInt(useTime % 60)
      seconds = seconds < 10 ? '0' + seconds : seconds
      let minutes = parseInt(useTime / 60 % 60)
      minutes = minutes < 10 ? '0' + minutes : minutes
      let hours = parseInt(useTime / 3600 % 60)
      hours = hours < 10 ? '0' + hours : hours
      return `${hours}:${minutes}:${seconds}`
    },
    // 根据Date格式的日期,返回 mm-dd hh:mm
    dateToString (date) {
      let months = date.getMonth() + 1
      months = months < 10 ? '0' + months : months
      let dates = date.getDate()
      dates = dates < 10 ? '0' + dates : dates
      let hours = date.getHours()
      hours = hours < 10 ? '0' + hours : hours
      let minutes = date.getMinutes()
      minutes = minutes < 10 ? '0' + minutes : minutes
      return `${months}-${dates} ${hours}:${minutes}`
    },
    // 框选
    // 鼠标按下事件
    boxStart (event, parentDom) {
      if (event.target.tagName === 'IMG' ||
        event.target.tagName === 'SPAN' ||
        event.target.className.indexOf('txt-ellipsis') > -1) {
        return true
      }
      // 判断鼠标是否是左键按下
      if (event.buttons !== 1 || event.which !== 1) return
      let parentNode = this.$refs[parentDom]
      this.parentX = getOffsetLeft(parentNode)
      this.parentY = getOffsetTop(parentNode)
      this.parentW = parentNode.clientWidth
      this.parentH = parentNode.clientHeight
      let self = this
      clearTimeout(this.mouseTime)
      let startTime = new Date()

      // 间隔300毫秒后执行，判断这时候鼠标左键被按住不放
      // this.mouseTime = setTimeout(() => {
      //   this.mouseOn = true
      //   this.startX = event.clientX - this.parentX
      //   this.startY = event.clientY - this.parentY
      //   let boxSelect = this.$refs.boxSelect
      //   boxSelect.style.display = 'block'
      //   boxSelect.style.left = this.startX + 'px'
      //   boxSelect.style.top = this.startY + 'px'
      //   boxSelect.style.width = 0
      //   boxSelect.style.height = 0
      // }, 1300)

      this.mouseOn = true
      this.startX = event.clientX - this.parentX
      this.startY = event.clientY - this.parentY
      let boxSelect = this.$refs.boxSelect
      boxSelect.style.display = 'block'
      boxSelect.style.left = this.startX + 'px'
      boxSelect.style.top = this.startY + 'px'
      boxSelect.style.zIndex = -1
      boxSelect.style.width = 0
      boxSelect.style.height = 0
      document.onmousemove = function (event) {
        self.boxMove(event, parentDom)
      }
      this.$refs[parentDom].onmouseup = function (event) {
        self.$refs[parentDom].onmousemove = null
        clearTimeout(this.mouseTime)
        let endTime = new Date()
        if (endTime.getTime() - startTime.getTime() < 200) {
          self.isClickEvent = true
        }
        self.boxStop(event)
      }
    },
    // 鼠标移动事件
    boxMove (event, parentDom) {
      // 如果框选没有开启。退出
      if (!this.mouseOn) return

      let clientX = event.clientX
      let clientY = event.clientY
      let _x = clientX - this.parentX
      let _y = clientY - this.parentY
      let boxSelect = this.$refs.boxSelect

      boxSelect.style.left = Math.min(_x, this.startX) + 'px'
      boxSelect.style.top = Math.min(_y, this.startY) + 'px'
      boxSelect.style.width = Math.abs(_x - this.startX) + 'px'
      boxSelect.style.height = Math.abs(_y - this.startY) + 'px'
      boxSelect.style.zIndex = 100
      this.findNodes(event)
      // 当框选超出范围时，结束框选操作,取消move和mouseup监听
      if (clientX < this.parentX || clientX > this.parentX + this.parentW || clientY < this.parentY || clientY > this.parentY + this.parentH) {
        document.onmousemove = null
        this.$refs[parentDom].onmouseup = null
        clearTimeout(this.mouseTime)

        this.boxStop(event)
      }
    },
    // 鼠标松开事件
    boxStop (event) {
      this.mouseOn = false
      this.findNodes(event)
      let boxSelect = this.$refs.boxSelect
      boxSelect.style.display = 'none'
      boxSelect.style.width = 0
      boxSelect.style.height = 0
    },
    // 获取框选下的元素
    findNodes (event) {
      let dayNodes = document.getElementsByClassName('cloud-file-item')
      let boxSelect = this.$refs.boxSelect
      let selectedEls = []
      // 获取框的参数
      let l = boxSelect.offsetLeft
      let t = boxSelect.offsetTop
      let w = boxSelect.offsetWidth
      let h = boxSelect.offsetHeight

      for (let i = 0; i < dayNodes.length; i++) {
        let dayNode = dayNodes[i]
        let sl = dayNode.offsetWidth + dayNode.offsetLeft
        let st = dayNode.offsetHeight + dayNode.offsetTop
        if (sl > l && st > t && dayNode.offsetLeft < l + w && dayNode.offsetTop < t + h) {
          selectedEls.push(this.files[i])
        }
      }
      if (event.ctrlKey || event.shiftKey) {
        this.actFile = this.actFile.concat(selectedEls)
      } else {
        this.actFile = selectedEls
      }
    },
    // 排序
    onRequest (props) {
      const { sortBy, descending } = props.pagination
      if (sortBy) {
        const sortFn = (descending
          ? (a, b) => (a[sortBy] > b[sortBy] ? -1 : a[sortBy] < b[sortBy] ? 1 : 0)
          : (a, b) => (a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0)
        )
        this.files = this.files.sort(sortFn)
        this.pagination.sortBy = sortBy
        this.pagination.descending = descending
      }
    },
    // 将云端路径中的租户id换成“所有文件”
    getShowCloudPath (path) {
      let pathArr = path.split('/')
      pathArr.shift()
      return '所有文件/' + pathArr.join('/')
    }
  },
  components: {
    CodeEdit,
    SendSureDialog,
    RecyclebinDialog,
    VersionList
  }
}
</script>

<style scoped lang="stylus">
.file-list{
  .file-list-head{
    .file-list-path{
      display inline-block
      width 400px
    }
  }
  .list-content{
    height calc(100% - 40px)
  }
  .list{
    padding 10px
    display flex
    flex-wrap wrap
    dl{
      margin-right 4px
      margin-bottom 4px
      padding 7px 3px
      width 84px
      height 95px
      font-size 14px
      box-sizing border-box
      text-align center
      border 1px solid #fff
      &.active, &:hover{
        background-color rgba(95,119,253, 0.2)
        border 1px solid $primary
      }
    }
    dt{
      text-align center
    }
    dd{
      .renameInput{
        position relative
        z-index 10
        background-color #fff
      }
    }
  }
  .table-file{
    height 100%
    .q-table__middle{
      height 100%
    }
    .active{
      background-color rgba(95,119,253, 0.2)
    }
    .name{
      display inline-block
      width 350px
      vertical-align middle
    }
    .renameInput{
      background-color #fff
    }
  }
}
.file-list-head{
  padding 0 20px
  height 40px
  line-height 40px
  font-size 14px
  .icon{
    margin-top 10px
    margin-left 10px
    font-size 18px
  }
}
.txt-ellipsis{
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  word-wrap: break-word;
}
// 框选样式
.box-select{
  position absolute
  margin 0
  padding 0
  top 0
  left 0
  width 10px
  height 10px
  border 1px dashed $primary
  background-color $primary
  z-index 1000
  opacity 0.6
  display none
}
</style>
<style lang="stylus">
.file-list  .table-file{
  .q-table__middle{
    height 100%
  }
}
</style>
